using NUnit.Framework;
using dnAnalytics.LinearAlgebra;
using dnAnalytics.LinearAlgebra.Solvers.Preconditioners;


namespace dnAnalytics.UnitTests.LinearAlgebra.Solvers.Preconditioners
{
    [TestFixture]
    [Category("Managed")]
    public sealed class DiagonalIncompleteLUFactorizationTest : PreconditionerTest
    {
        internal override IPreconditioner CreatePreconditioner(SparseMatrix matrix)
        {
            return new DiagonalIncompleteLUFactorization(matrix);
        }

        protected override void CheckResult(IPreconditioner preconditioner, Vector vector, Vector result)
        {
            Assert.AreEqual(typeof(DiagonalIncompleteLUFactorization), preconditioner.GetType(), "#01");

            DiagonalIncompleteLUFactorization factorization = preconditioner as DiagonalIncompleteLUFactorization;
            // Get the Upper triangular matrix U
            // Get the Lower triangular matrix L
            // Get the diagonal matrix D
            // M = (D + L) * D^-1 * (D + U)
            // Compute M * result = product
            // compare vector and product. Should be equal
            Matrix l = factorization.LowerTriagonalMatrix();
            Matrix u = factorization.UpperTriagonalMatrix();
            Matrix d = factorization.DiagonalMatrix();
            l.Add(d);
            u.Add(d);
            // invert D --> inverse each item in D as D is diagonal
            for (int i = 0; i < d.Rows; i++)
            {
                d[i,i] = 1.0 / d[i,i];
            }
            
            Matrix temp = d.Multiply(u);
            Matrix temp2 = l.Multiply(temp);
            
            Vector product = VectorBuilder.CreateVector(result.Count, VectorType.Dense);
            temp2.Multiply(result, product);

            for (int i = 0; i < product.Count; i++)
            {
                Assert.AreEqual(vector[i], product[i], epsilon, "#02-" + i.ToString());
            }
        }
    }
}